package ia.programas.server.base;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.logging.Logger;


/**
 * Clase padre de los paquetes enviados por el servidor a los clientes.
 * 
 * 
 * @author Armando Andini
 * 
 */
public abstract class ServerBasePacket  {

	private static Logger _log = Logger.getLogger(ServerBasePacket.class.getName());
	protected ByteArrayOutputStream _bao;

	protected ServerBasePacket() {
		_bao = new ByteArrayOutputStream();
		_log.finest(getType());
	}

	/**
	 * Escribir un entero de 4 bytes en el paquete
	 * 
	 * @param value
	 */
	protected void writeL(long value) {
		_bao.write((int) (value & 0xff));
		_bao.write((int) (value >> 8 & 0xff));
		_bao.write((int) (value >> 16 & 0xff));
		_bao.write((int) (value >> 24 & 0xff));
	}

	/**
	 * Escribir un entero de 2 bytes en el paquete
	 * 
	 * @param value
	 */
	protected void writeI(int value) {
		_bao.write(value & 0xff);
		_bao.write(value >> 8 & 0xff);

	}

	/**
	 * Escribir un entero de 2 bytes al reves en el paquete
	 * 
	 * @param value
	 */
	protected void writeIDiverted(int value) {
		_bao.write(value >> 8 & 0xff);
		_bao.write(value & 0xff);

	}

	/**
	 * Escribir 1 byte en el paquete
	 * 
	 * @param value
	 */
	protected void writeC(int value) {
		_bao.write(value & 0xff);
	}

	/**
	 * Escribir un double en el paquete
	 * 
	 * @param org
	 */
	protected void writeF(double org) {
		final long value = Double.doubleToRawLongBits(org);
		_bao.write((int) (value & 0xff));
		_bao.write((int) (value >> 8 & 0xff));
		_bao.write((int) (value >> 16 & 0xff));
		_bao.write((int) (value >> 24 & 0xff));
		_bao.write((int) (value >> 32 & 0xff));
		_bao.write((int) (value >> 40 & 0xff));
		_bao.write((int) (value >> 48 & 0xff));
		_bao.write((int) (value >> 56 & 0xff));
	}

	/**
	 * Escribir un conjunto de bytes
	 * 
	 * @param a
	 */
	protected void writeB(byte[] a) {
		try {
			_bao.write(a);
		} catch (final Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Escribir un string en el paquete
	 * 
	 * @param text
	 */
	protected void writeS(String text) {
		try {
			if (text != null) {
				_bao.write(text.getBytes("ISO-8859-1"));
			}
		} catch (final Exception e) {
			e.printStackTrace();
		}
	}

	
	/**
	 * no usado
	 * @return
	 */
	public abstract String getType();
	
	/**
	 * Cada paquete debe retornar aca una cabecera que lo identifique
	 * @return
	 */
	public abstract int getHeader();
	
	/**
	 * escribe la longitud del paquete y la cabecera al principio del paquete
	 * @param size
	 */
	public void makeHeader(int size){
		this.writeI(size);
		this.writeC(this.getHeader());
	}
	
	/**
	 * return lengh of byte array
	 * 
	 * @return
	 */
	public int getLength() {
		return _bao.size();
	}
	
	
	/**
	 * Este metodo es el principal en cada paquete del server.
	 * Aca debe armar el paquete en base a sus parametros, y retornar el arreglo
	 * de bytes para enviar directamente
	 * 
	 * @return
	 * @throws IOException
	 * @throws Throwable
	 */
	public abstract byte[] getContent() throws IOException;
	
	/**
	 * obtener los bytes almacenados en el buffer
	 * @return
	 */
	public byte[] getBytes() {
		return _bao.toByteArray();
	}
}
